﻿// Copyright (c) 2010 Dan Popick

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

using log4net;

namespace Open.Web.Stijl.Utility
{
    public class Tracer<T>
    {
		/// <summary>
		/// Internal class used to separate the construction of Tracer from access to the optional log4net library
		/// </summary>
		class Log4NetLogger
		{
			public ILog Log;

			public Log4NetLogger()
			{
				Type t = typeof(T);
				if (t.IsGenericType)
				{
					// hack to omit full type names in the output for generic classes
					string genTypes = String.Join(", ", t.GetGenericArguments().Select(x => x.Name).ToArray());
					string name = String.Format("{0}.{1}<{2}>", t.Namespace, t.Name, genTypes);
					Log = LogManager.GetLogger(name);
				}
				else
					Log = LogManager.GetLogger(typeof(T));
			}

			public bool IsDebugEnabled { get { return Log.IsDebugEnabled; } }
			public bool IsInfoEnabled { get { return Log.IsInfoEnabled; } }
			public bool IsWarnEnabled { get { return Log.IsWarnEnabled; } }
			public bool IsErrorEnabled { get { return Log.IsErrorEnabled; } }

			public void Debug(string message) { Log.Debug(message); }
			public void Debug(string message, params object[] args) { Log.DebugFormat(message, args); }
			public void Debug(string message, Exception ex) { Log.Debug(message, ex); }
			public void Info(string message) { Log.Info(message); }
			public void Info(string message, params object[] args) { Log.InfoFormat(message, args); }
			public void Info(string message, Exception ex) { Log.Info(message, ex); }
			public void Warn(string message) { Log.Warn(message); }
			public void Warn(string message, params object[] args) { Log.WarnFormat(message, args); }
			public void Warn(string message, Exception ex) { Log.Warn(message, ex); }
			public void Error(string message) { Log.Error(message); }
			public void Error(string message, params object[] args) { Log.ErrorFormat(message, args); }
			public void Error(string message, Exception ex) { Log.Error(message, ex); }
		}

        TraceSource _source = new TraceSource("Open.Web.Stijl");
		Log4NetLogger _logWrapper;

		public Tracer()
		{
			try
			{
				_logWrapper = new Log4NetLogger();
			}
			catch
			{
				_logWrapper = null;
			}
		}

		public bool IsDebugEnabled { 
			get { 
				return (_logWrapper == null) 
					? _source.Switch.ShouldTrace(TraceEventType.Verbose) 
					: _logWrapper.IsDebugEnabled; 
			} 
		}
		public bool IsInfoEnabled { 
			get { 
				return (_logWrapper == null) 
					? _source.Switch.ShouldTrace(TraceEventType.Information) 
					: _logWrapper.IsInfoEnabled; 
			} 
		}
		public bool IsWarnEnabled { 
			get { 
				return (_logWrapper == null) 
					? _source.Switch.ShouldTrace(TraceEventType.Warning) 
					: _logWrapper.IsWarnEnabled; 
			} 
		}
		public bool IsErrorEnabled { 
			get { 
				return (_logWrapper == null) 
					? _source.Switch.ShouldTrace(TraceEventType.Error) 
					: _logWrapper.IsErrorEnabled; 
			} 
		}

        public void Debug(string message)
        {
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Verbose, 0, message);
			else
				_logWrapper.Debug(message);
        }

		public void Debug(string format, params object[] args)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Verbose, 0, String.Format(format, args));
			else
				_logWrapper.Debug(format, args);
		}

		public void Debug(string message, Exception ex)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Verbose, 0, message + " - " + ex.ToString());
			else
				_logWrapper.Debug(message, ex);
		}

		public void Info(string message)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Information, 0, message);
			else
				_logWrapper.Info(message);
		}

		public void Info(string format, params object[] args)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Information, 0, String.Format(format, args));
			else
				_logWrapper.Info(format, args);
		}

		public void Info(string message, Exception ex)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Information, 0, message + " - " + ex.ToString());
			else
				_logWrapper.Info(message, ex);
		}

		public void Warn(string message)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Warning, 0, message);
			else
				_logWrapper.Warn(message);
		}

		public void Warn(string format, params object[] args)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Warning, 0, String.Format(format, args));
			else
				_logWrapper.Warn(format, args);
		}

		public void Warn(string message, Exception ex)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Warning, 0, message + " - " + ex.ToString());
			else
				_logWrapper.Warn(message, ex);
		}

		public void Error(string message)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Error, 0, message);
			else
				_logWrapper.Error(message);
		}

		public void Error(string format, params object[] args)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Error, 0, String.Format(format, args));
			else
				_logWrapper.Error(format, args);
		}

		public void Error(string message, Exception ex)
		{
			if (_logWrapper == null)
				_source.TraceEvent(TraceEventType.Error, 0, message + " - " + ex.ToString());
			else
				_logWrapper.Error(message, ex);
		}

		public void Error(Exception ex, string format, params object[] args)
		{
			string message = String.Format(format, args);
			Error(message, ex);
		}
	}
}
